home *** CD-ROM | disk | FTP | other *** search
Text File | 1997-03-17 | 13.6 KB | 543 lines | [TEXT/CWIE] |
- //
- // CQD3DPane.cp
- //
- // class CQD3DPane [abstract]
- // A Pane for rendering a QuickDraw 3D view.
- //
- // by James Jennings
- // November 21, 1995
- //
-
- #include "CQD3DPane.h"
- #include "StQ3Disposer.h"
- #include "QD3D Debug Macros.h"
-
- #include "CDrawContextMaker.h"
- #include "CRendererMaker.h"
- #include "CCameraMaker.h"
- #include "C3Lights.h"
-
- #include "CBoxMaker.h"
-
- #include <QD3DGeometry.h>
- #include <QD3DShader.h>
- #include <QD3DCamera.h>
- #include <QD3DLight.h>
- #include <QD3DGroup.h>
- #include <QD3DRenderer.h>
- #include <QD3DDrawContext.h>
- #include <QD3DMath.h>
- #include <QD3DTransform.h>
- #include <QD3DAcceleration.h> // defines kQAVendor_BestChoice
-
- Boolean CQD3DPane::sSawFatalError = false; // Stop processing when there is a fatal error.
- Boolean CQD3DPane::sNowSubmitting = false; // Keep submitting loops from being reentrant.
-
- CQD3DPane* CQD3DPane::CreateFromStream(LStream *inStream)
- {
- return new CQD3DPane( inStream );
- }
-
- CQD3DPane::CQD3DPane()
- : mView(0), mModel(0), mInterpolation(0), mBackFacing(0), mFillStyle(0),
- mLights(0), mCamera(0), mDrawContext(0), mRenderer(0), mDefaultAttributes(0)
- { // default constructor
- // Does nothing. QD3D Objects are built when needed.
- }
-
- CQD3DPane::CQD3DPane(const CQD3DPane &inOriginal) : LPane(inOriginal),
- mView(0), mModel(0), mInterpolation(0), mBackFacing(0), mFillStyle(0),
- mLights(0), mCamera(0), mDrawContext(0), mRenderer(0), mDefaultAttributes(0)
- { // copy constructor
- SignalPStr_("\pcopy constructor needs rewriting.");
- /*
- mView = ::Q3Object_Duplicate(inOriginal.mView);
- ThrowIfNil_(mView);
- mModel = ::Q3Shared_GetReference(inOriginal.mModel);
- mInterpolation = ::Q3Shared_GetReference(inOriginal.mInterpolation);
- mBackFacing = ::Q3Shared_GetReference(inOriginal.mBackFacing);
- mFillStyle = ::Q3Shared_GetReference(inOriginal.mFillStyle);
- */
- }
-
- CQD3DPane::CQD3DPane(LStream *inStream) : LPane(inStream),
- mView(0), mModel(0), mInterpolation(0), mBackFacing(0), mFillStyle(0),
- mLights(0), mCamera(0), mDrawContext(0), mRenderer(0), mDefaultAttributes(0)
- { // stream constructor
- // Does nothing. QD3D Objects are built when needed.
- // (That's one way to make it exception safe.)
- }
-
- CQD3DPane::~CQD3DPane()
- { // destructor
-
- Q3Forget( mFillStyle );
- Q3Forget( mBackFacing );
- Q3Forget( mInterpolation );
- Q3Forget( mLights );
- Q3Forget( mCamera );
- Q3Forget( mDrawContext );
- Q3Forget( mRenderer );
- Q3Forget( mModel );
- Q3Forget( mView );
- Q3Forget( mDefaultAttributes );
- }
-
- void CQD3DPane::RebuildView()
- {
- Q3Forget( mView );
- }
-
- void CQD3DPane::ResizeFrameBy(
- Int16 inWidthDelta,
- Int16 inHeightDelta,
- Boolean inRefresh)
- {
- LPane::ResizeFrameBy( inWidthDelta, inHeightDelta, inRefresh );
-
- // We need to adjust the Q3View to fit the new pane size
- AdjustQ3ViewToFrame();
- }
-
- void CQD3DPane::MoveBy(
- Int32 inHorizDelta,
- Int32 inVertDelta,
- Boolean inRefresh)
- {
- LPane::ResizeFrameBy( inHorizDelta, inVertDelta, inRefresh );
-
- // We need to adjust the Q3View to fit the new pane size
- AdjustQ3ViewToFrame();
- }
-
- void CQD3DPane::AdjustQ3ViewToFrame()
- {
- // Adjust the camera to fit the pane size
- if ( GetCamera() && ::Q3Camera_GetType(GetCamera()) == kQ3CameraTypeViewAngleAspect ) {
-
- SDimension16 frameSize;
- GetFrameSize( frameSize );
-
- Assert_( frameSize.width > 0 && frameSize.height > 0 );
- float aspect = (float) (frameSize.width) / (float) (frameSize.height);
-
- TQ3Status status = ::Q3ViewAngleAspectCamera_SetAspectRatio( GetCamera(), aspect );
- ThrowIfQ3Fail_( status );
-
- }
-
- // Adjust the draw context to fit the pane size
- if ( GetDrawContext() != nil ) {
-
- Rect frame;
- CalcLocalFrameRect( frame );
-
- TQ3Area pane;
- ::Q3Point2D_Set( &pane.min, frame.left, frame.top );
- ::Q3Point2D_Set( &pane.max, frame.right, frame.bottom );
-
- TQ3Status status = ::Q3DrawContext_SetPane( GetDrawContext(), &pane );
- ThrowIfQ3Fail_( status );
- }
- }
-
- #pragma mark === Object Getters ===
-
- TQ3StyleObject CQD3DPane::GetInterpolation()
- {
- if (mInterpolation==0)
- mInterpolation = ::Q3InterpolationStyle_New( GetInterpolationStyle() ) ;
-
- ThrowIfNil_( mInterpolation );
- return mInterpolation;
- }
-
- TQ3StyleObject CQD3DPane::GetBackFacing()
- {
- if (mBackFacing==0)
- mBackFacing = ::Q3BackfacingStyle_New( GetBackfacingStyle() ) ;
-
- ThrowIfNil_( mBackFacing );
- return mBackFacing;
- }
-
- TQ3StyleObject CQD3DPane::GetFill()
- {
- if (mFillStyle==0)
- mFillStyle = ::Q3FillStyle_New( GetFillStyle() ) ;
-
- ThrowIfNil_( mFillStyle );
- return mFillStyle;
- }
-
- TQ3DrawContextObject CQD3DPane::GetDrawContext(void)
- {
- if ( mDrawContext == nil ) {
-
- Rect theFrame;
- CalcLocalFrameRect( theFrame );
-
- CDrawContextMaker maker( (CGrafPtr) GetMacPort(), theFrame );
- mDrawContext = maker.GetRef();
-
- }
-
- return mDrawContext;
- }
-
- void CQD3DPane::SetClearImageColor(const TQ3ColorARGB &inColor)
- {
- TQ3DrawContextObject theContext = GetDrawContext();
- Assert_(theContext != nil);
- TQ3Status theStatus = ::Q3DrawContext_SetClearImageColor(theContext,&inColor);
- Assert_(theStatus == kQ3Success);
- }
-
- void CQD3DPane::GetClearImageColor(TQ3ColorARGB &outColor)
- {
- TQ3DrawContextObject theContext = GetDrawContext();
- Assert_(theContext != nil);
- TQ3Status theStatus = ::Q3DrawContext_GetClearImageColor(theContext,&outColor);
- Assert_(theStatus == kQ3Success);
- }
-
- void CQD3DPane::SetRenderer(TQ3RendererObject inRenderer)
- {
- Assert_( inRenderer != nil );
-
- Q3Forget(mRenderer);
- RebuildView(); // forces the view to be rebuilt
-
- mRenderer = ::Q3Shared_GetReference( inRenderer );
- }
-
- TQ3RendererObject CQD3DPane::GetRenderer(void)
- {
- if ( mRenderer == nil ) {
- CRendererMaker maker;
- mRenderer = maker.GetRef();
- }
-
- return mRenderer;
- }
-
- void CQD3DPane::SetModel( TQ3GroupObject inGroup )
- {
- Assert_( inGroup != nil );
-
- Q3Forget( mModel );
- RebuildView(); // forces the view to be rebuilt
-
- mModel = ::Q3Shared_GetReference( inGroup );
- }
-
- TQ3GroupObject CQD3DPane::GetModel(void)
- {
- if ( mModel == nil ) {
- // No model was supplied. Make something to look at.
- CBoxMaker maker;
-
- // Make a group to put it in
- mModel = ::Q3DisplayGroup_New();
- ThrowIfNil_(mModel);
-
- TQ3GroupPosition pos;
- pos = ::Q3Group_AddObject( mModel, maker.Get() );
- ThrowIf_(pos==0);
-
- }
-
- return mModel;
- }
-
- void CQD3DPane::SetCamera( TQ3CameraObject inCamera )
- {
- Assert_( inCamera != nil );
-
- Q3Forget( mCamera );
- RebuildView(); // forces the view to be rebuilt
-
- mCamera = ::Q3Shared_GetReference( inCamera );
-
- // Adjust the camera to the size of the pane.
- AdjustQ3ViewToFrame();
- }
-
- TQ3CameraObject CQD3DPane::GetCamera(void)
- {
- if ( mCamera == nil ) {
- // No camera was supplied. Make something to see with.
- SDimension16 theSize;
- GetFrameSize( theSize );
-
- CCameraMaker maker( theSize );
-
- mCamera = maker.GetRef();
- }
-
- return mCamera;
- }
-
- void CQD3DPane::SetLights( TQ3GroupObject inLights )
- {
- Assert_( inLights != nil );
-
- Q3Forget( mLights );
- RebuildView(); // forces the view to be rebuilt
-
- mLights = ::Q3Shared_GetReference( inLights );
- }
-
- TQ3GroupObject CQD3DPane::GetLights(void)
- {
- if ( mLights == nil ) {
- // No camera was supplied. Make something to see with.
-
- C3Lights maker;
-
- mLights = maker.GetRef();
- }
-
- return mLights;
- }
-
- void CQD3DPane::SetDefaultAttributes(TQ3AttributeSet inAttributes)
- {
- Assert_(inAttributes != nil);
-
- Q3Forget(mDefaultAttributes);
- RebuildView(); // forces the view to be rebuilt
-
- mDefaultAttributes = ::Q3Shared_GetReference(inAttributes);
- }
-
- TQ3AttributeSet CQD3DPane::GetDefaultAttributes(void)
- {
- SignalPStr_("\pGetDefaultAttributes() not yet implimented");
- return nil;
- }
-
- void CQD3DPane::SetViewHints(TQ3ViewHintsObject inHints)
- {
- // If there are no hints, ignore them.
- if (inHints == nil) return;
-
- TQ3Status theStatus;
-
- TQ3RendererObject theRenderer;
- theStatus = ::Q3ViewHints_GetRenderer(inHints, &theRenderer);
- if (theStatus == kQ3Success && theRenderer != nil) {
- SetRenderer(theRenderer);
- Q3Forget(theRenderer);
- }
-
- TQ3CameraObject theCamera;
- theStatus = ::Q3ViewHints_GetCamera(inHints, &theCamera);
- // Note: I expected that theStatus would be kQ3Fail if there were no camera
- // but I have a bug report to the contrary. So now I check for theCamera != nil as well.
- if (theStatus == kQ3Success && theCamera != nil) {
- SetCamera(theCamera);
- Q3Forget(theCamera);
- }
-
- TQ3GroupObject theLightGroup;
- theStatus = ::Q3ViewHints_GetLightGroup(inHints, &theLightGroup);
- if (theStatus == kQ3Success && theLightGroup != nil) {
- SetLights(theLightGroup);
- Q3Forget(theLightGroup);
- }
-
- TQ3AttributeSet theAttributes;
- theStatus = ::Q3ViewHints_GetAttributeSet(inHints, &theAttributes);
- if (theStatus == kQ3Success && theAttributes != nil) {
- SetDefaultAttributes(theAttributes);
- Q3Forget(theAttributes);
- }
-
- // For TQ3DrawContext related stuff
- TQ3DrawContextObject theContext = GetDrawContext();
- Assert_(theContext != nil);
-
- TQ3Boolean dimensionsAreValid;
- theStatus = ::Q3ViewHints_GetDimensionsState(inHints, &dimensionsAreValid);
- if (theStatus == kQ3Success) {
- // SetDimensionsState(isValid);
- }
-
- if (dimensionsAreValid) {
- unsigned long theWidth, theHeight;
- theStatus = ::Q3ViewHints_GetDimensions(inHints, &theWidth, &theHeight);
- if (theStatus == kQ3Success) {
- // SetDimensions(theWidth, theHeight);
- }
- }
-
- TQ3Boolean maskIsValid;
- theStatus = ::Q3ViewHints_GetMaskState(inHints, &maskIsValid);
- if (theStatus == kQ3Success) {
- theStatus = ::Q3DrawContext_SetMaskState(theContext,maskIsValid);
- Assert_(theStatus == kQ3Success);
- }
- if (maskIsValid) {
- TQ3Bitmap theMask = {0,0,0,0};
- theStatus = ::Q3ViewHints_GetMask(inHints, &theMask);
- if (theStatus == kQ3Success) {
- theStatus = ::Q3DrawContext_SetMask(theContext,&theMask);
- Assert_(theStatus == kQ3Success);
- theStatus = ::Q3Bitmap_Empty( &theMask );
- Assert_(theStatus == kQ3Success);
- }
- }
-
-
- TQ3DrawContextClearImageMethod theMethod; // ???
- theStatus = ::Q3ViewHints_GetClearImageMethod(inHints, &theMethod);
- if (theStatus == kQ3Success) {
- theStatus = ::Q3DrawContext_SetClearImageMethod(theContext,theMethod);
- Assert_(theStatus == kQ3Success);
- }
-
- TQ3ColorARGB theColor;
- theStatus = ::Q3ViewHints_GetClearImageColor(inHints, &theColor);
- if (theStatus == kQ3Success) {
- SetClearImageColor(theColor); // Ha! We have a method for that!
- }
-
- }
-
- TQ3ViewObject CQD3DPane::GetView()
- {
- // A View must have a Camera, a Renderer, and a Draw Context.
- // The lights are optional.
-
- TQ3Status status;
-
- if ( mView == 0 ) {
-
- mView = ::Q3View_New();
- ThrowIfNil_(mView);
-
- status = ::Q3View_SetDrawContext(mView, GetDrawContext() );
- ThrowIfQ3Fail_(status);
-
- status = ::Q3View_SetRenderer(mView, GetRenderer() );
- ThrowIfQ3Fail_(status);
-
- status = ::Q3View_SetCamera(mView, GetCamera() );
- ThrowIfQ3Fail_(status);
-
- status = ::Q3View_SetLightGroup(mView, GetLights() );
- ThrowIfQ3Fail_(status);
-
- if (mDefaultAttributes) {
- status = ::Q3View_SetDefaultAttributeSet(mView, mDefaultAttributes);
- ThrowIfQ3Fail_(status);
- }
- }
-
- return mView;
- }
-
- #pragma mark === Drawing/Submitting ===
-
- void CQD3DPane::DrawSelf()
- { // Your basic submitting loop.
-
- // we don't enter the submit loop after a fatal error,
- // or if we are already submitting something
- if (sSawFatalError) return;
- if (sNowSubmitting) return;
- StSubmittingSetter theSetter; // sets sNowSubmitting
-
- TQ3Status status;
- TQ3ViewStatus viewStatus;
- status = ::Q3View_StartRendering(GetView());
- ThrowIfQ3Fail_(status);
- try {
- do {
- status = SubmitScene();
- viewStatus = ::Q3View_EndRendering(GetView());
- } while ( viewStatus == kQ3ViewStatusRetraverse );
- }
- catch (...) {
- // if something threw an exception, we need to stop rendering
- status = ::Q3View_Cancel(GetView());
- throw;
- }
- }
-
- void CQD3DPane::CalcBoundingBox(TQ3BoundingBox &outBox, TQ3ComputeBounds inComputeBounds)
- { // Your basic submitting loop.
-
- Assert_(inComputeBounds==kQ3ComputeBoundsApproximate || inComputeBounds==kQ3ComputeBoundsExact);
-
- // we don't enter the submit loop after a fatal error,
- // or if we are already submitting something
- if (sSawFatalError) return;
- if (sNowSubmitting) return;
- StSubmittingSetter theSetter; // sets sNowSubmitting
-
- TQ3Status status;
- TQ3ViewStatus viewStatus;
- status = ::Q3View_StartBoundingBox(GetView(), inComputeBounds);
- ThrowIfQ3Fail_(status);
- try {
- do {
- // status = SubmitScene();
- status = ::Q3DisplayGroup_Submit( GetModel(), GetView() );
- viewStatus = ::Q3View_EndBoundingBox(GetView(), &outBox);
- } while ( viewStatus == kQ3ViewStatusRetraverse );
- }
- catch (...) {
- // if something threw an exception, we need to stop rendering
- status = ::Q3View_Cancel(GetView());
- throw;
- }
- }
-
- void CQD3DPane::Write( TQ3FileObject inFile )
- { // Your basic submitting loop.
- // we don't enter the submit loop after a fatal error,
- // or if we are already submitting something
- if (sSawFatalError) return;
- if (sNowSubmitting) return;
- StSubmittingSetter theSetter; // sets sNowSubmitting
-
- TQ3Status status;
- TQ3ViewStatus viewStatus;
- status = ::Q3View_StartWriting(GetView(), inFile);
- ThrowIfQ3Fail_(status);
- try {
- do {
- status = SubmitScene();
- // status = ::Q3DisplayGroup_Submit( GetModel(), GetView() );
- viewStatus = ::Q3View_EndWriting( GetView() );
- } while ( viewStatus == kQ3ViewStatusRetraverse );
- }
- catch (...) {
- // if something threw an exception, we need to stop rendering
- status = ::Q3View_Cancel(GetView());
- throw;
- }
- }
-
- TQ3Status
- CQD3DPane::SubmitScene()
- { // As recommended in develop 23, we separate the body
- // of the Submit loop so it may be used for other things
- // than rendering.
- TQ3Status status;
- status = ::Q3Style_Submit( GetInterpolation(), GetView() );
- if (status==kQ3Failure) return status;
-
- status = ::Q3Style_Submit( GetBackFacing(), GetView() );
- if (status==kQ3Failure) return status;
-
- status = ::Q3Style_Submit( GetFill(), GetView() );
- if (status==kQ3Failure) return status;
-
- status = ::Q3DisplayGroup_Submit( GetModel(), GetView() );
- return status;
- }
-
-